#!/usr/bin/perl
use strict;
use FindBin;
use IO::File;
use Getopt::Long;
use File::Basename;
use HTTP::Tiny;
use File::Path;
use File::Spec;

use ServerConf;
use AutoExecUtils;

sub usage {
    my $pname = $FindBin::Script;

    print("Usage: $pname [--verbose 0|1]\n");
    print("              [--addr FtpAddress] [--dest DestinationDirectory] \n");
    print("              [--user username] [--pass password] \n");
    print("\n");
    print("       --addr:      Ftp address\n");
    print("       --dir:       Remote target path .\n");
    print("       --user:      Ftp user name .\n");
    print("       --pass:      Password .\n");
    exit(1);
}

sub main {
    my ( $isHelp, $isVerbose );
    my ( $node, $addr, $localDir, $user, $pass );

    my $pname = $FindBin::Script;

    my $isVerbose = 0;

    GetOptions(
        'h|help'      => \$isHelp,
        'v|verbose=i' => \$isVerbose,
        'addr=s'      => \$addr,
        'dir=s'       => \$localDir,
        'user=s'      => \$user,
        'pass=s'      => \$pass
    );

    usage() if ( defined($isHelp) );

    my $optionError = 0;

    if ( not defined($addr) or $addr eq '' ) {
        print("ERROR: Must define ftp url.\n");
        $optionError = 1;
    }

    if ( not defined($localDir) or $localDir eq '' ) {
        $localDir = '.';
    }

    if ( $localDir =~ /\/\.\.\// or $localDir =~ /^\.\.\// or $localDir =~ /\/\.\.$/ ) {
        print("ERROR: Dest path can not has parent dir opertor:\"..\".\n");
        $optionError = 1;
    }

    if ( $addr !~ /^https?:\/\// ) {
        $optionError = 1;
        print("ERROR: Invalid http address:$addr, example: http://192.168.0.222/test\n");
    }

    if ( $optionError == 1 ) {
        usage();
    }

    if ( defined($pass) and $pass ne '' ) {
        my $serverConf = ServerConf->new();
        $pass = $serverConf->decryptPwd($pass);
    }

    my $saveTargetPath;
    my $errorCode = 0;

    if ( !-e $localDir ) {
        $errorCode = 1;
        print("ERROR: Directory $localDir not exists.\n");
    }
    elsif ( !-d $localDir ) {
        $errorCode = 1;
        print("ERROR: $localDir is not a directory.\n");
    }
    else {
        my $headers = {};
        if ( defined($user) and $user ne '' ) {
            my $authToken = 'Basic ' . MIME::Base64::encode( $user . ':' . $pass );
            $authToken =~ s/\s*$//;
            $headers->{Authorization} = $authToken;
        }

        my $http = HTTP::Tiny->new();

        my $localFile;
        if ( -d $localDir ) {
            $localFile = "$localDir/" . basename($addr);
        }
        else {
            $localFile = $localDir;
        }

        my $response = $http->mirror( $addr, $localFile, { headers => $headers } );
        if ( $response->{success} ) {
            print("FINE: Download $addr to $localFile success.\n");
            $saveTargetPath = File::Spec->canonpath($localFile);
        }
        else {
            $errorCode = $errorCode + 1;
            my $content = $response->{content};
            print("ERROR: Download $addr to $localFile failed.\n$content.\n");
        }
    }

    my $out = {};
    $out->{filePath} = $saveTargetPath;
    AutoExecUtils::saveOutput($out);

    return $errorCode;
}

exit main();

